home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / usenet / volume11 / tinymud2 / part09 < prev    next >
Encoding:
Internet Message Format  |  1990-08-10  |  55.3 KB

  1. Path: uunet!zephyr.ens.tek.com!tekred!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v11i013:  tinymud2 - user-extendible multi-user adventure (v1.5.4), Part09/10
  5. Message-ID: <6058@tekred.CNA.TEK.COM>
  6. Date: 30 Jul 90 16:46:44 GMT
  7. Sender: news@tekred.CNA.TEK.COM
  8. Lines: 2088
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: James Aspnes <asp@cs.cmu.edu>
  12. Posting-number: Volume 11, Issue 13
  13. Archive-name: tinymud2/Part09
  14. Supersedes: tinymud: Volume 8, Issue 80-83
  15.  
  16.  
  17.  
  18. #! /bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 9 (of 10)."
  25. # Contents:  CHANGES compress.c create.c db.h match.c move.c
  26. #   predicates.c speech.c
  27. # Wrapped by billr@saab on Fri Jul 27 15:27:50 1990
  28. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  29. if test -f 'CHANGES' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'CHANGES'\"
  31. else
  32. echo shar: Extracting \"'CHANGES'\" \(7507 characters\)
  33. sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
  34. X------------------------------------------------------------------------
  35. X
  36. XChanges in Islandia Version (1.5.4) by Fuzzy (Michael Mauldin)
  37. X
  38. X25-Jun-90    Allow people to drop exits they are carrying that
  39. X        have location -1 (this fixes a problem with exits
  40. X        that get recycled while they are carried).
  41. X
  42. X9-Jun-90    Added failure message for whispers to objects
  43. X        Made DUMPCORE on error the default (writes DB,
  44. X          then calls abort() with SIGILL enabled).  Set
  45. X          -DNODUMPCORE to inhibit core dumps.
  46. X        Unified Islandia & TinyHELL sources, with switch
  47. X          in config.h
  48. X        Added Virus (Robert Hood's) port concentrator.
  49. X        Added connect.txt, for messages before the connect.
  50. X        
  51. X        There are now 5 text files associated with TinyMUD:
  52. X            connect.txt    before logging in
  53. X            motd.txt    after logging in
  54. X            tinker.txt    after logging in for tinkers
  55. X            news.txt    News command
  56. X            help.txt    Help command
  57. X
  58. X17-Jun-90    Added Virus's concentrator code.
  59. X        Fixed extract to allow player names instead of numbers,
  60. X          and added special commands: reachable, players,
  61. X          norecycle a<num> b<num>
  62. X        
  63. X------------------------------------------------------------------------
  64. X
  65. XChanges in Islandia/Hell Version (1.5.3C) by Random (Russ Smith)
  66. X
  67. X5-Jun-90    Made ABODE govern dropto
  68. X        Allow players to DARKen objects that they own and are
  69. X          carrying, but not let them drop DARK objects in an
  70. X          area they couldn't link to.
  71. X        Added UNWANTED flag, which allows people to @chown
  72. X          objects to themselves, subject to locking;
  73. X        Made @chown understand 'me'
  74. X        Made @recycle set its object to be UNWANTED
  75. X        Made page and whisper check the WHO list and
  76. X          respond appropriately.
  77. X
  78. X------------------------------------------------------------------------
  79. X
  80. XChanges in Islandia Version (1.5.3B) by Fuzzy (Michael Mauldin)
  81. X
  82. X31-May-90    Added casts to signal arguments to get rid of
  83. X        annoying warnings from gcc.
  84. X
  85. X28-May-90    Added @count & @recycle...@count is redundant with
  86. X        @stat for players, but it can also be run by
  87. X        non-tinkers, and @count of a room summarizes
  88. X        contents: a new feature.  Note that @count is
  89. X        less work than @find, because only the db array
  90. X        is used, no strings are referenced.
  91. X
  92. X        Also fixed bug in extract:
  93. X
  94. X            extract all -<player>
  95. X
  96. X        now extracts player and his contents...before,
  97. X        a bug/feature/omission caused only the player
  98. X        to be extracted.
  99. X
  100. X        Syntax:
  101. X
  102. X        @count <player>
  103. X        @count <room>
  104. X
  105. X        @recycle <thing> = <recipient>
  106. X        @recycle <thing>        defaults to Recycler.
  107. X
  108. X        Recycling an object destroys its strings, and chowns
  109. X        the object to a player called Recycler.  The idea is
  110. X        that periodically you can "extract all -<recycler-num>"
  111. X        to remove the recycled objects.
  112. X
  113. X        Added code to extract to check for isolated rooms
  114. X        (no entrances, or no entrances, exits, or contents).
  115. X
  116. X        Fixed bug/feature in extract that caused it to complain
  117. X        aboute unlinked exits being carried by players.  It no
  118. X        longer complains about them.
  119. X
  120. X28-May-90    Added NOFAKES switch to forbid use of names that
  121. X        are really first words from important system messages
  122. X        (A, An, The, You, Your, Going, Huh?)
  123. X
  124. X25-May-90:    Added code to @bobble to chown all the players
  125. X        objects to another user.
  126. X
  127. X20-May-90:    Added ROBOT flag...enables OUTPUTPREFIX/SUFFIX,
  128. X        prevents ROBOT players from getting objects,
  129. X        using exits, or entering rooms with ROBOT set.
  130. X
  131. X        Changed Wizards to Tinkers, Temples to Junkpiles,
  132. X        and 'sacrifice' to 'donate'.  Added special
  133. X        MOTD for Tinkers (file ../lib/tinker.txt).
  134. X
  135. X        Also changed @toad to @bobble.
  136. X
  137. X        Fixed problem with @link on links that are
  138. X        set to *home*.
  139. X
  140. X        Fixed security hole that allowed a Wizard to
  141. X        @force God...thus preventing
  142. X
  143. X            @force Wizard = @set *Apprentice = WIZARD
  144. X
  145. X        Changed game.c so that on errors both a database
  146. X        dump and a regular core dump are written.
  147. X
  148. X17-May-90:    Fixed bug where @name guest = foo bar caused
  149. X        a crash because guest has no password (file set.c)
  150. X
  151. X        Added MOTD function, file ../lib/motd.txt
  152. X        (files help.c, interface.c)
  153. X
  154. X        Added caching of hostnames so that Tinkers can do a
  155. X        WHO without bogging down the server.
  156. X
  157. X11-May-90    Added Random's "page <name> = <msg>" command, to allow
  158. X        sending messages simply...people otherwise used
  159. X        
  160. X           @name me = <msg> / @page <name> / @name me = <desc>
  161. X
  162. X        anyway, so why not make it easy.
  163. X
  164. X------------------------------------------------------------------------
  165. X
  166. XChanges in Firefoot version (1.5.3A) (Scott Goehring):
  167. X
  168. XAdded code to detach netmud from the terminal on startup (-DDETACH).
  169. X
  170. XNetmud now writes to a log file instead of stderr when detached.
  171. XSIGUSR2 will close and reopen the log file.
  172. X
  173. XSIGTERM and SIGINT now cause netmud to shutdown cleanly instead of
  174. Xpanicking (good for when your system is /etc/shutdown'd).
  175. X
  176. XAdded parallel compile support to the makefile (if you're on a
  177. XSequent, compile with 'make P=\&').
  178. X
  179. XLog file entries are now preceded by the time of day.
  180. X
  181. XThe status dumper (SIGUSR1) has been removed.
  182. X
  183. XAdded Random's preregistration support (disabled create, @pcreate).
  184. X
  185. XAdded OJ's examine hack.
  186. X
  187. XAdded Random's @owned command.
  188. X
  189. XPanics now dump the contents of the sigcontext struct in hex to the
  190. Xlogfile for debugging purposes.
  191. X
  192. X
  193. XChanges in version 1.5.3-FF.1 (Scott Goehring):
  194. X
  195. XWHO can take an argument; only names with the same prefix as the
  196. Xargument are displayed.
  197. X
  198. XLINK_OK code modified; ABODE flag added.
  199. X
  200. XPlayer may select format and order of WHO listing.
  201. X
  202. X!-bug fixed properly.
  203. X
  204. X------------------------------------------------------------------------
  205. X
  206. XChanges in version 1.5.3:
  207. X
  208. XGripes now get sent immediately to GOD when GOD_PRIV is defined.  They
  209. Xcan be blocked by setting HAVEN.
  210. X
  211. XLimited @newpassword command to GOD when GOD_PRIV is defined.  Otherwise
  212. Xany WIZARD could subvert GOD.
  213. X
  214. XAdded special case to do_name for changing the case of a player name.
  215. X
  216. XAdded interface changes, GOD_PRIV hacks, and HAVEN bit. [These Changes
  217. Xfrom Random at TinyHELL]
  218. X
  219. XGot rid of LOOKUP_COST; replaced it with special FIND_COST and PAGE_COST.  
  220. Xfind defaults to being very expensive.
  221. X
  222. XAdded hash table for player name lookups.  This change should
  223. Xeliminate a lot of thrashing.
  224. X
  225. XFixed ok_name test so that ! can appear after the beginning of a name.
  226. X
  227. X
  228. XChanges in version 1.5.2:
  229. X
  230. XAdded Stephen White's pronoun substitution code under #ifdef GENDER.
  231. X
  232. XChanged test for setting a created object's home to current room to
  233. Xrequire control of the room instead of linkability.
  234. X
  235. XObjects sent to rooms with @teleport go through dropto's.
  236. X
  237. XBoolean operators can no longer appear in names.
  238. X
  239. XAdded rudimentary string compression under #ifdef COMPRESS.
  240. X
  241. XFixed missing OUTPUTPREFIX and OUTPUTSUFFIX on WHO command in interface.
  242. X
  243. XFixed various small bugs not caught in 1.5.1.
  244. X
  245. X
  246. XChanges in version 1.5.1:
  247. X
  248. X@newpassword command added.  Password checking added.  1p charge for
  249. Xchanging your own name eliminated to prevent confusion.
  250. X
  251. XDatabase structure modified to allow for boolean expressions as keys.
  252. XUSE_VFORK, DB_INITIAL_SIZE, and DB_DOUBLING #defines added to allow
  253. Xfor greater system-dependent configuration.
  254. X
  255. XWhisper command added.
  256. X
  257. XName formatting centralized.  Names now include flags.
  258. X
  259. Xok_player_name() modified to reject names longer than
  260. XPLAYER_NAME_LIMIT.
  261. X
  262. XBoolean lock code added.
  263. X
  264. X
  265. XChanges in version 1.4.2:
  266. X
  267. XSmall bug fixes; okname() modified to reject names containing
  268. XARG_DELIMITER, democratized teleport added under #ifndef
  269. XRESTRICTED_TELEPORT.
  270. X
  271. X
  272. XChanges in version 1.4.1:
  273. X
  274. XRadically rewritten interface.c with fair command processing, command limits.
  275. X
  276. X------------------------------------------------------------------------
  277. END_OF_FILE
  278. if test 7507 -ne `wc -c <'CHANGES'`; then
  279.     echo shar: \"'CHANGES'\" unpacked with wrong size!
  280. fi
  281. # end of 'CHANGES'
  282. fi
  283. if test -f 'compress.c' -a "${1}" != "-c" ; then 
  284.   echo shar: Will not clobber existing file \"'compress.c'\"
  285. else
  286. echo shar: Extracting \"'compress.c'\" \(2725 characters\)
  287. sed "s/^X//" >'compress.c' <<'END_OF_FILE'
  288. X/* Compression routines */
  289. X
  290. X/* These use a pathetically simple encoding that takes advantage of the */
  291. X/* eighth bit on a char; if you are using an international character set, */
  292. X/* they may need substantial patching. */
  293. X
  294. X#ifdef COMPRESS
  295. X
  296. X#define BUFFER_LEN 16384    /* nice big buffer */
  297. X
  298. X#define TOKEN_BIT 0x80        /* if on, it's a token */
  299. X#define TOKEN_MASK 0x7f        /* for stripping out token value */
  300. X#define NUM_TOKENS (128)
  301. X#define MAX_CHAR (128)
  302. X
  303. X/* Top 128 bigrams in the CMU TinyMUD database as of 2/13/90 */ 
  304. Xstatic const char *tokens[NUM_TOKENS] = {
  305. X    "e ", " t", "th", "he", "s ", " a", "ou", "in",
  306. X    "t ", " s", "er", "d ", "re", "an", "n ", " i",
  307. X    " o", "es", "st", "to", "or", "nd", "o ", "ar",
  308. X    "r ", ", ", "on", " b", "ea", "it", "u ", " w",
  309. X    "ng", "le", "is", "te", "en", "at", " c", "y ",
  310. X    "ro", " f", "oo", "al", ". ", "a ", " d", "ut",
  311. X    " h", "se", "nt", "ll", "g ", "yo", " l", " y",
  312. X    " p", "ve", "f ", "as", "om", "of", "ha", "ed",
  313. X    "h ", "hi", " r", "lo", "Yo", " m", "ne", "l ",
  314. X    "li", "de", "el", "ta", "wa", "ri", "ee", "ti",
  315. X    "no", "do", "Th", " e", "ck", "ur", "ow", "la",
  316. X    "ac", "et", "me", "il", " g", "ra", "co", "ch",
  317. X    "ma", "un", "so", "rt", "ai", "ce", "ic", "be",
  318. X    " n", "k ", "ge", "ot", "si", "pe", "tr", "wi",
  319. X    "e.", "ca", "rs", "ly", "ad", "we", "bo", "ho",
  320. X    "ir", "fo", "ke", "us", "m ", " T", "di", ".." };
  321. X
  322. Xstatic char token_table[MAX_CHAR][MAX_CHAR];
  323. Xstatic int table_initialized = 0;
  324. X
  325. Xstatic void init_compress(void)
  326. X{
  327. X    int i;
  328. X    int j;
  329. X
  330. X    for(i = 0; i < MAX_CHAR; i++) {
  331. X    for(j = 0; j < MAX_CHAR; j++) {
  332. X        token_table[i][j] = 0;
  333. X    }
  334. X    }
  335. X
  336. X    for(i = 0; i < NUM_TOKENS; i++) {
  337. X    token_table[tokens[i][0]][tokens[i][1]] = i | TOKEN_BIT;
  338. X    }
  339. X
  340. X    table_initialized = 1;
  341. X}
  342. X
  343. Xstatic int compressed(const char *s)
  344. X{
  345. X    while(*s) {
  346. X    if(*s++ & TOKEN_BIT) return 1;
  347. X    }
  348. X    return 0;
  349. X}
  350. X
  351. Xconst char *compress(const char *s)
  352. X{
  353. X    static char buf[BUFFER_LEN];
  354. X    char *to;
  355. X    char token;
  356. X
  357. X    if(!table_initialized) init_compress();
  358. X
  359. X    if(compressed(s)) return s;    /* already compressed */
  360. X
  361. X    /* tokenize the first characters */
  362. X    for(to = buf; s[0] && s[1]; to++) {
  363. X    if(token = token_table[s[0]][s[1]]) {
  364. X        *to = token;
  365. X        s += 2;
  366. X    } else {
  367. X        *to = s[0];
  368. X        s++;
  369. X    }
  370. X    }
  371. X
  372. X    /* copy the last character (if any) and null */
  373. X    while(*to++ = *s++);
  374. X
  375. X    return buf;
  376. X}
  377. X    
  378. Xconst char *uncompress(const char *s)
  379. X{
  380. X    static char buf[BUFFER_LEN];
  381. X    char *to;
  382. X    const char *token;
  383. X
  384. X    for(to = buf; *s; s++) {
  385. X    if(*s & TOKEN_BIT) {
  386. X        token = tokens[*s & TOKEN_MASK];
  387. X        *to++ = *token++;
  388. X        *to++ = *token;
  389. X    } else {
  390. X        *to++ = *s;
  391. X    }
  392. X    }
  393. X
  394. X    *to++ = *s;
  395. X
  396. X    return buf;
  397. X}
  398. X
  399. X#endif /* COMPRESS */
  400. X        
  401. END_OF_FILE
  402. if test 2725 -ne `wc -c <'compress.c'`; then
  403.     echo shar: \"'compress.c'\" unpacked with wrong size!
  404. fi
  405. # end of 'compress.c'
  406. fi
  407. if test -f 'create.c' -a "${1}" != "-c" ; then 
  408.   echo shar: Will not clobber existing file \"'create.c'\"
  409. else
  410. echo shar: Extracting \"'create.c'\" \(8647 characters\)
  411. sed "s/^X//" >'create.c' <<'END_OF_FILE'
  412. X#include "copyright.h"
  413. X
  414. X/* Commands that create new objects */
  415. X
  416. X#include "db.h"
  417. X#include "config.h"
  418. X#include "interface.h"
  419. X#include "externs.h"
  420. X
  421. X/* utility for open and link */
  422. Xstatic dbref parse_linkable_room(dbref player, object_flag_type thing,
  423. X                 const char *room_name)
  424. X{
  425. X    dbref room;
  426. X
  427. X    /* skip leading NUMBER_TOKEN if any */
  428. X    if(*room_name == NUMBER_TOKEN) room_name++;
  429. X
  430. X    /* parse room */
  431. X    if(!string_compare(room_name, "here")) {
  432. X    room = db[player].location;
  433. X    } else if(!string_compare(room_name, "home")) {
  434. X    return HOME;        /* HOME is always linkable */
  435. X    } else {
  436. X    room = parse_dbref(room_name);
  437. X    }
  438. X
  439. X    /* check room */
  440. X    if(room < 0 || room >= db_top
  441. X       || Typeof(room) != TYPE_ROOM) {
  442. X    notify(player, "That's not a room!");
  443. X    return NOTHING;
  444. X    } else if(!can_link_to(player, thing, room)) {
  445. X    notify(player, "You can't link to that.");
  446. X    return NOTHING;
  447. X    } else {
  448. X    return room;
  449. X    }
  450. X}
  451. X
  452. X/* use this to create an exit */
  453. Xvoid do_open(dbref player, const char *direction, const char *linkto)
  454. X{
  455. X    dbref loc;
  456. X    dbref exit;
  457. X
  458. X#ifdef RESTRICTED_BUILDING
  459. X    if(!Builder(player)) {
  460. X    notify(player, "That command is restricted to authorized builders.");
  461. X    return;
  462. X    }
  463. X#endif /* RESTRICTED_BUILDING */
  464. X
  465. X    if((loc = getloc(player)) == NOTHING) return;
  466. X    if(!*direction) {
  467. X    notify(player, "Open where?");
  468. X    return;
  469. X    } else if(!ok_name(direction)) {
  470. X    notify(player, "That's a strange name for an exit!");
  471. X    return;
  472. X    }
  473. X
  474. X    if(!controls(player, loc)) {
  475. X    notify(player, "Permission denied.");
  476. X    } else if(!payfor(player, EXIT_COST)) {
  477. X    notify(player,
  478. X           "Sorry, you don't have enough pennies to open an exit.");
  479. X    } else {
  480. X    /* create the exit */
  481. X    exit = new_object();
  482. X
  483. X    /* initialize everything */
  484. X    db[exit].name = alloc_string(direction);
  485. X    db[exit].owner = player;
  486. X    db[exit].flags = TYPE_EXIT;
  487. X
  488. X    /* link it in */
  489. X    PUSH(exit, db[loc].exits);
  490. X
  491. X    /* and we're done */
  492. X    notify(player, "Opened.");
  493. X
  494. X    /* check second arg to see if we should do a link */
  495. X    if(*linkto != '\0') {
  496. X        notify(player, "Trying to link...");
  497. X        if((loc = parse_linkable_room(player, TYPE_EXIT, linkto)) !=
  498. X           NOTHING) {
  499. X        if(!payfor(player, LINK_COST)) {
  500. X            notify(player, "You don't have enough pennies to link.");
  501. X        } else {
  502. X            /* it's ok, link it */
  503. X            db[exit].location = loc;
  504. X            notify(player, "Linked.");
  505. X        }
  506. X        }
  507. X    }
  508. X    }
  509. X}
  510. X
  511. X/* use this to link to a room that you own */
  512. X/* it seizes ownership of the exit */
  513. X/* costs 1 penny */
  514. X/* plus a penny transferred to the exit owner if they aren't you */
  515. X/* you must own the linked-to room AND specify it by room number */
  516. Xvoid do_link(dbref player, const char *name, const char *room_name)
  517. X{
  518. X    dbref thing;
  519. X    dbref room;
  520. X
  521. X    init_match(player, name, TYPE_EXIT);
  522. X    match_exit();
  523. X    match_neighbor();
  524. X    match_possession();
  525. X    match_me();
  526. X    match_here();
  527. X    if(Wizard(player)) {
  528. X    match_absolute();
  529. X    match_player();
  530. X    }
  531. X
  532. X    if((thing = noisy_match_result()) != NOTHING) {
  533. X    if((room = parse_linkable_room(player, Typeof(thing), room_name)) ==
  534. X       NOTHING)
  535. X        return;
  536. X    switch(Typeof(thing)) {
  537. X      case TYPE_EXIT:
  538. X        /* we're ok, check the usual stuff */
  539. X        if(db[thing].location != NOTHING) {
  540. X        if(controls(player, thing)) {
  541. X
  542. X            /*
  543. X             * Changed 5/18/90 Fuzzy - exits linked to *home*
  544. X             * break 'Typeof() call'
  545. X             */
  546. X
  547. X            if(db[thing].location >= 0 &&
  548. X               Typeof(db[thing].location) == TYPE_PLAYER) {
  549. X            notify(player, "That exit is being carried.");
  550. X            } else {
  551. X            notify(player, "That exit is already linked.");
  552. X            }
  553. X        } else {
  554. X            notify(player, "Permission denied.");
  555. X        }
  556. X        } else {
  557. X        /* handle costs */
  558. X        if(db[thing].owner == player) {
  559. X            if(!payfor(player, LINK_COST)) {
  560. X            notify(player,
  561. X                   "It costs a penny to link this exit.");
  562. X            return;
  563. X            }
  564. X        } else {
  565. X            if(!payfor(player, LINK_COST + EXIT_COST)) {
  566. X            notify(player,
  567. X                   "It costs two pennies to link this exit.");
  568. X            return;
  569. X#ifdef RESTRICTED_BUILDING
  570. X            } else if(!Builder(player)) {
  571. X            notify(player,
  572. X                   "Only authorized builders may seize exits.");
  573. X#endif /* RESTRICTED_BUILDING */            
  574. X            } else {
  575. X            /* pay the owner for his loss */
  576. X            db[db[thing].owner].pennies += EXIT_COST;
  577. X            }
  578. X        }
  579. X
  580. X        /* link has been validated and paid for; do it */
  581. X        db[thing].owner = player;
  582. X        db[thing].location = room;
  583. X
  584. X        /* notify the player */
  585. X        notify(player, "Linked.");
  586. X        }
  587. X        break;
  588. X      case TYPE_PLAYER:
  589. X      case TYPE_THING:
  590. X        if(!controls(player, thing)) {
  591. X        notify(player, "Permission denied.");
  592. X        } else if(room == HOME) {
  593. X        notify(player, "Can't set home to home.");
  594. X        } else {
  595. X        /* do the link */
  596. X        db[thing].exits = room; /* home */
  597. X        notify(player, "Home set.");
  598. X        }
  599. X        break;
  600. X      case TYPE_ROOM:
  601. X        if(!controls(player, thing)) {
  602. X        notify(player, "Permission denied.");
  603. X        } else {
  604. X        /* do the link, in location */
  605. X        db[thing].location = room; /* dropto */
  606. X        notify(player, "Dropto set.");
  607. X        }
  608. X        break;
  609. X      default:
  610. X        notify(player, "Internal error: weird object type.");
  611. X        writelog("PANIC weird object: Typeof(%d) = %d\n",
  612. X            thing, Typeof(thing));
  613. X        break;
  614. X    }
  615. X    }
  616. X}
  617. X
  618. X/* use this to create a room */
  619. Xvoid do_dig(dbref player, const char *name)
  620. X{
  621. X    dbref room;
  622. X    char buf[BUFFER_LEN];
  623. X
  624. X#ifdef RESTRICTED_BUILDING
  625. X    if(!Builder(player)) {
  626. X    notify(player, "That command is restricted to authorized builders.");
  627. X    return;
  628. X    }
  629. X#endif /* RESTRICTED_BUILDING */
  630. X
  631. X    /* we don't need to know player's location!  hooray! */
  632. X    if(*name == '\0') {
  633. X    notify(player, "Dig what?");
  634. X    } else if(!ok_name(name)) {
  635. X    notify(player, "That's a silly name for a room!");
  636. X    } else if(!payfor(player, ROOM_COST)) {
  637. X    notify(player, "Sorry, you don't have enough pennies to dig a room.");
  638. X    } else {
  639. X    room = new_object();
  640. X
  641. X    /* Initialize everything */
  642. X    db[room].name = alloc_string(name);
  643. X    db[room].owner = player;
  644. X    db[room].flags = TYPE_ROOM;
  645. X
  646. X    sprintf(buf, "%s created with room number %d.", name, room);
  647. X    notify(player, buf);
  648. X    }
  649. X}
  650. X
  651. X/* use this to create an object */
  652. Xvoid do_create(dbref player, char *name, int cost)
  653. X{
  654. X    dbref loc;
  655. X    dbref thing;
  656. X
  657. X#ifdef RESTRICTED_BUILDING
  658. X    if(!Builder(player)) {
  659. X    notify(player, "That command is restricted to authorized builders.");
  660. X    return;
  661. X    }
  662. X#endif /* RESTRICTED_BUILDING */
  663. X
  664. X    if(*name == '\0') {
  665. X    notify(player, "Create what?");
  666. X    return;
  667. X    } else if(!ok_name(name)) {
  668. X    notify(player, "That's a silly name for a thing!");
  669. X    return;
  670. X    } else if(cost < 0) {
  671. X    notify(player, "You can't create an object for less than nothing!");
  672. X    return;
  673. X    } else if(cost < OBJECT_COST) {
  674. X    cost = OBJECT_COST;
  675. X    }
  676. X
  677. X    if(!payfor(player, cost)) {
  678. X    notify(player, "Sorry, you don't have enough pennies.");
  679. X    } else {
  680. X    /* create the object */
  681. X    thing = new_object();
  682. X
  683. X    /* initialize everything */
  684. X    db[thing].name = alloc_string(name);
  685. X    db[thing].location = player;
  686. X    db[thing].owner = player;
  687. X    db[thing].pennies = OBJECT_ENDOWMENT(cost);
  688. X    db[thing].flags = TYPE_THING;
  689. X
  690. X    /* endow the object */
  691. X    if(db[thing].pennies > MAX_OBJECT_ENDOWMENT) {
  692. X        db[thing].pennies = MAX_OBJECT_ENDOWMENT;
  693. X    }
  694. X
  695. X    /* home is here (if we can link to it) or player's home */
  696. X    if((loc = db[player].location) != NOTHING
  697. X       && controls(player, loc)) {
  698. X        db[thing].exits = loc;    /* home */
  699. X    } else {
  700. X        db[thing].exits = db[player].exits;    /* home */
  701. X    }
  702. X
  703. X    /* link it in */
  704. X    PUSH(thing, db[player].contents);
  705. X
  706. X    /* and we're done */
  707. X    notify(player, "Created.");
  708. X    }
  709. X}
  710. X
  711. X#ifdef REGISTRATION
  712. Xvoid do_pcreate (dbref player, char *newplayer, char *newpass)
  713. X{
  714. X    dbref ptmp;
  715. X
  716. X#ifdef GOD_MODE && GOD_ONLY_PCREATE
  717. X    if (!God(player))
  718. X#ifndef TINKER
  719. X        notify (player, "Only GOD can create a new player.");
  720. X#else TINKER
  721. X        notify (player, "Only the Master Tinker can create a new player.");
  722. X#endif TINKER
  723. X#else GOD_MODE && GOD_ONLY_PCREATE
  724. X    if (!Wizard(player))
  725. X#ifndef TINKER
  726. X    notify (player, "Only a Wizard can create a new player.");
  727. X#else TINKER
  728. X    notify (player, "Only a Tinker can create a new player.");
  729. X#endif TINKER
  730. X#endif GOD_MODE && GOD_ONLY_PCREATE
  731. X    else if (!*newplayer || !*newpass)
  732. X    notify (player, "You must specify name and password.");
  733. X    else {
  734. X        ptmp = create_player (newplayer, newpass);
  735. X    if (ptmp == NOTHING) {
  736. X        notify(player, "Either there is already a player with that name, or that name is illegal.");
  737. X        writelog("FAILED CREATE %s by %s\n",newplayer,db[player].name);
  738. X    } else {
  739. X        char buf[512];
  740. X        sprintf(buf, "%s created as object #%d.",db[ptmp].name,ptmp);
  741. X        notify(player, buf);
  742. X        writelog("CREATED %s(%d) by %s\n",db[ptmp].name,ptmp,
  743. X             db[player].name);
  744. X    }
  745. X    }
  746. X}
  747. X#endif REGISTRATION
  748. END_OF_FILE
  749. if test 8647 -ne `wc -c <'create.c'`; then
  750.     echo shar: \"'create.c'\" unpacked with wrong size!
  751. fi
  752. # end of 'create.c'
  753. fi
  754. if test -f 'db.h' -a "${1}" != "-c" ; then 
  755.   echo shar: Will not clobber existing file \"'db.h'\"
  756. else
  757. echo shar: Extracting \"'db.h'\" \(5703 characters\)
  758. sed "s/^X//" >'db.h' <<'END_OF_FILE'
  759. X#include "copyright.h"
  760. X
  761. X#ifndef __DB_H
  762. X#define __DB_H
  763. X#include <stdio.h>
  764. X
  765. Xextern void *malloc(unsigned long);
  766. Xextern void *realloc(void *, unsigned long);
  767. Xextern void free(void *);
  768. X
  769. X#ifdef TEST_MALLOC
  770. Xextern int malloc_count;
  771. X#define malloc(x) (malloc_count++, malloc(x))
  772. X#define free(x) (malloc_count--, free(x))
  773. X#endif /* TEST_MALLOC */
  774. X
  775. Xtypedef int dbref;        /* offset into db */
  776. X
  777. X#define TYPE_ROOM     0x0
  778. X#define TYPE_THING     0x1
  779. X#define TYPE_EXIT     0x2
  780. X#define TYPE_PLAYER     0x3
  781. X#define NOTYPE        0x7    /* no particular type */
  782. X#define TYPE_MASK     0x7    /* room for expansion */
  783. X#define ANTILOCK    0x8    /* negates key (*OBSOLETE*) */
  784. X#define WIZARD        0x10    /* gets automatic control */
  785. X#define LINK_OK        0x20    /* anybody can link exits to this room */
  786. X#define DARK        0x40    /* contents of room are not printed */
  787. X#define TEMPLE        0x80    /* objects dropped in this room go home */
  788. X#define STICKY        0x100    /* this object goes home when dropped */
  789. X
  790. X#ifdef RESTRICTED_BUILDING
  791. X#define BUILDER        0x200    /* this player can use construction commands */
  792. X#endif /* RESTRICTED_BUILDING */
  793. X
  794. X#define HAVEN           0x400   /* this room prohibits killing */
  795. X#define ABODE           0x800   /* can link objects or players here */
  796. X
  797. X#ifdef GENDER
  798. X#define GENDER_MASK    0x3000    /* 2 bits of gender */
  799. X#define GENDER_SHIFT    12    /* 0x1000 is 12 bits over (for shifting) */
  800. X#define GENDER_UNASSIGNED    0x0    /* unassigned - the default */
  801. X#define GENDER_NEUTER    0x1    /* neuter */
  802. X#define GENDER_FEMALE    0x2    /* for women */
  803. X#define GENDER_MALE    0x3    /* for men */
  804. X
  805. X#ifdef ROBOT_MODE
  806. X#define ROBOT        0x4000  /* Can set OUTPUTPREFIX */
  807. X#endif ROBOT_MODE
  808. X
  809. X#define UNWANTED        0x8000  /* can be chowned */
  810. X
  811. X#define TABULAR_WHO     0x10000
  812. X#define REVERSED_WHO    0x20000
  813. X
  814. X#define Genderof(x) ((db[(x)].flags & GENDER_MASK) >> GENDER_SHIFT)
  815. X#endif /* GENDER */
  816. X
  817. Xtypedef int object_flag_type;
  818. X
  819. X#define Flag(x,f) ((db[(x)].flags & (f)) != 0)
  820. X
  821. X#define Typeof(x) (db[(x)].flags & TYPE_MASK)
  822. X#define Wizard(x) ((db[(x)].flags & WIZARD) != 0)
  823. X#ifdef ROBOT_MODE
  824. X#define Robot(x) ((db[(x)].flags & ROBOT) != 0)
  825. X#endif ROBOT_MODE
  826. X#define Dark(x) ((db[(x)].flags & DARK) != 0)
  827. X#ifdef GOD_PRIV
  828. X#define GOD ((dbref)1)
  829. X#define    God(x) ((x)==GOD)
  830. X#endif GOD_PRIV
  831. X
  832. X#ifdef RECYCLE
  833. X#define RECYCLER "Recycler"
  834. X#endif
  835. X
  836. X#ifdef RESTRICTED_BUILDING
  837. X#define Builder(x) ((db[(x)].flags & (WIZARD|BUILDER)) != 0)
  838. X#endif /* RESTRICTED_BUILDING */
  839. X
  840. X/* Boolean expressions, for locks */
  841. Xtypedef char boolexp_type;
  842. X
  843. X#define BOOLEXP_AND 0
  844. X#define BOOLEXP_OR 1
  845. X#define BOOLEXP_NOT 2
  846. X#define BOOLEXP_CONST 3
  847. X
  848. Xstruct boolexp {
  849. X  boolexp_type type;
  850. X  struct boolexp *sub1;
  851. X  struct boolexp *sub2;
  852. X  dbref thing;
  853. X};
  854. X
  855. X#define TRUE_BOOLEXP ((struct boolexp *) 0)
  856. X
  857. X/* special dbref's */
  858. X#define NOTHING (-1)        /* null dbref */
  859. X#define AMBIGUOUS (-2)        /* multiple possibilities, for matchers */
  860. X#define HOME (-3)        /* virtual room, represents mover's home */
  861. X
  862. Xstruct object {
  863. X    const char *name;            
  864. X    const char *description;        
  865. X    dbref location;        /* pointer to container */
  866. X                /* for exits, pointer to destination */
  867. X    dbref contents;        /* pointer to first item */
  868. X    dbref exits;        /* pointer to first exit for rooms */
  869. X                    /* pointer to home for things and players */
  870. X    dbref next;            /* pointer to next in contents/exits chain */
  871. X
  872. X    /* the following are used for pickups for things, entry for exits */
  873. X    struct boolexp *key;    /* if not NOTHING, must have this to do op */
  874. X    const char *fail_message;        /* what you see if op fails */
  875. X    const char *succ_message;        /* what you see if op succeeds */
  876. X    /* other messages get your name prepended, so if your name is "Foo", */
  877. X    /* and osuccess = "disappears in a blast of gamma radiation." */
  878. X    /* then others see "Foo disappears in a blast of gamma radiation." */
  879. X    /* (At some point I may put in Maven-style %-substitutions.) */
  880. X    const char *ofail;        /* what others see if op fails */
  881. X    const char *osuccess;    /* what others see if op succeeds */
  882. X
  883. X    dbref owner;        /* who controls this object */
  884. X    int pennies;        /* number of pennies object contains */
  885. X    object_flag_type flags;
  886. X    const char *password;    /* password for players */
  887. X};
  888. X
  889. Xextern struct object *db;
  890. Xextern dbref db_top;
  891. X
  892. Xextern const char *alloc_string(const char *s);
  893. X
  894. Xextern dbref new_object();    /* return a new object */
  895. X
  896. Xextern dbref getref (FILE *);   /* Read a database reference from a file. */
  897. X
  898. Xextern void putref (FILE *, dbref); /* Write one ref to the file */
  899. X
  900. Xextern struct boolexp *getboolexp(FILE *); /* get a boolexp */
  901. Xextern void putboolexp(FILE *, struct boolexp *); /* put a boolexp */
  902. X
  903. Xextern int db_write_object(FILE *, dbref); /* write one object to file */
  904. X
  905. Xextern dbref db_write(FILE *f);    /* write db to file, return # of objects */
  906. X
  907. Xextern dbref db_read(FILE *f);    /* read db from file, return # of objects */
  908. X                /* Warning: destroys existing db contents! */
  909. X
  910. Xextern void free_boolexp(struct boolexp *);
  911. Xextern void db_free(void);
  912. X
  913. Xextern dbref parse_dbref(const char *);    /* parse a dbref */
  914. X
  915. X#define DOLIST(var, first) \
  916. X  for((var) = (first); (var) != NOTHING; (var) = db[(var)].next)
  917. X#define PUSH(thing, locative) \
  918. X    ((db[(thing)].next = (locative)), (locative) = (thing))
  919. X#define getloc(thing) (db[thing].location)
  920. X
  921. X/*
  922. X  Usage guidelines:
  923. X
  924. X  To refer to objects use db[object_ref].  Pointers to objects may 
  925. X  become invalid after a call to new_object().
  926. X
  927. X  The programmer is responsible for managing storage for string
  928. X  components of entries; db_read will produce malloc'd strings.  The
  929. X  alloc_string routine is provided for generating malloc'd strings
  930. X  duplicates of other strings.  Note that db_free and db_read will
  931. X  attempt to free any non-NULL string that exists in db when they are
  932. X  invoked.  
  933. X*/
  934. X#endif /* __DB_H */
  935. END_OF_FILE
  936. if test 5703 -ne `wc -c <'db.h'`; then
  937.     echo shar: \"'db.h'\" unpacked with wrong size!
  938. fi
  939. # end of 'db.h'
  940. fi
  941. if test -f 'match.c' -a "${1}" != "-c" ; then 
  942.   echo shar: Will not clobber existing file \"'match.c'\"
  943. else
  944. echo shar: Extracting \"'match.c'\" \(5261 characters\)
  945. sed "s/^X//" >'match.c' <<'END_OF_FILE'
  946. X#include "copyright.h"
  947. X
  948. X/* Routines for parsing arguments */
  949. X#include <ctype.h>
  950. X
  951. X#include "db.h"
  952. X#include "config.h"
  953. X#include "match.h"
  954. X
  955. X#define DOWNCASE(x) (isupper(x) ? tolower(x) : (x))
  956. X
  957. Xstatic dbref exact_match = NOTHING;    /* holds result of exact match */
  958. Xstatic int check_keys = 0;    /* if non-zero, check for keys */
  959. Xstatic dbref last_match = NOTHING;    /* holds result of last match */
  960. Xstatic int match_count;        /* holds total number of inexact matches */
  961. Xstatic dbref match_who;    /* player who is being matched around */
  962. Xstatic const char *match_name;    /* name to match */
  963. Xstatic int preferred_type = NOTYPE; /* preferred type */
  964. X
  965. Xvoid init_match(dbref player, const char *name, int type)
  966. X{
  967. X    exact_match = last_match = NOTHING;
  968. X    match_count = 0;
  969. X    match_who = player;
  970. X    match_name = name;
  971. X    check_keys = 0;
  972. X    preferred_type = type;
  973. X}
  974. X
  975. Xvoid init_match_check_keys(dbref player, const char *name, int type)
  976. X{
  977. X    init_match(player, name, type);
  978. X    check_keys = 1;
  979. X}
  980. X
  981. Xstatic dbref choose_thing(dbref thing1, dbref thing2)
  982. X{
  983. X    int has1;
  984. X    int has2;
  985. X
  986. X    if(thing1 == NOTHING) {
  987. X    return thing2;
  988. X    } else if(thing2 == NOTHING) {
  989. X    return thing1;
  990. X    }
  991. X
  992. X    if(preferred_type != NOTYPE) {
  993. X    if(Typeof(thing1) == preferred_type) {
  994. X        if(Typeof(thing2) != preferred_type) {
  995. X        return thing1;
  996. X        }
  997. X    } else if(Typeof(thing2) == preferred_type) {
  998. X        return thing2;
  999. X    }
  1000. X    }
  1001. X
  1002. X    if(check_keys) {
  1003. X    has1 = could_doit(match_who, thing1);
  1004. X    has2 = could_doit(match_who, thing2);
  1005. X
  1006. X    if(has1 && !has2) {
  1007. X        return thing1;
  1008. X    } else if (has2 && !has1) {
  1009. X        return thing2;
  1010. X    }
  1011. X    /* else fall through */
  1012. X    }
  1013. X
  1014. X    return (random() % 2 ? thing1 : thing2);
  1015. X}
  1016. X
  1017. Xvoid match_player(void)
  1018. X{
  1019. X    dbref match;
  1020. X    const char *p;
  1021. X
  1022. X    if(*match_name == LOOKUP_TOKEN) {
  1023. X    for(p = match_name + 1; isspace(*p); p++);
  1024. X    if((match = lookup_player(p)) != NOTHING) {
  1025. X        exact_match = match;
  1026. X    }
  1027. X    }
  1028. X}
  1029. X
  1030. X/* returns nnn if name = #nnn, else NOTHING */
  1031. Xstatic dbref absolute_name(void)
  1032. X{
  1033. X    dbref match;
  1034. X
  1035. X    if(*match_name == NUMBER_TOKEN) {
  1036. X    match = parse_dbref(match_name+1);
  1037. X    if(match < 0 || match >= db_top) {
  1038. X        return NOTHING;
  1039. X    } else {
  1040. X        return match;
  1041. X    }
  1042. X    } else {
  1043. X    return NOTHING;
  1044. X    }
  1045. X}
  1046. X
  1047. Xvoid match_absolute(void)
  1048. X{
  1049. X    dbref match;
  1050. X
  1051. X    if((match = absolute_name()) != NOTHING) {
  1052. X    exact_match = match;
  1053. X    }
  1054. X}
  1055. X
  1056. Xvoid match_me(void)
  1057. X{
  1058. X    if(!string_compare(match_name, "me")) {
  1059. X    exact_match = match_who;
  1060. X    }
  1061. X}
  1062. X
  1063. Xvoid match_here(void)
  1064. X{
  1065. X    if(!string_compare(match_name, "here")
  1066. X       && db[match_who].location != NOTHING) {
  1067. X    exact_match = db[match_who].location;
  1068. X    }
  1069. X}
  1070. X
  1071. Xstatic void match_list(dbref first)
  1072. X{
  1073. X    dbref absolute;
  1074. X
  1075. X    absolute = absolute_name();
  1076. X    if(!controls(match_who, absolute)) absolute = NOTHING;
  1077. X
  1078. X    DOLIST(first, first) {
  1079. X    if(first == absolute) {
  1080. X        exact_match = first;
  1081. X        return;
  1082. X    } else if(!string_compare(db[first].name, match_name)) {
  1083. X        /* if there are multiple exact matches, randomly choose one */
  1084. X        exact_match = choose_thing(exact_match, first);
  1085. X    } else if(string_match(db[first].name, match_name)) {
  1086. X        last_match = first;
  1087. X        match_count++;
  1088. X    }
  1089. X    }
  1090. X}
  1091. X    
  1092. Xvoid match_possession(void)
  1093. X{
  1094. X    match_list(db[match_who].contents);
  1095. X}
  1096. X
  1097. Xvoid match_neighbor(void)
  1098. X{
  1099. X    dbref loc;
  1100. X
  1101. X    if((loc = db[match_who].location) != NOTHING) {
  1102. X    match_list(db[loc].contents);
  1103. X    }
  1104. X}
  1105. X
  1106. Xvoid match_exit(void)
  1107. X{
  1108. X    dbref loc;
  1109. X    dbref exit;
  1110. X    dbref absolute;
  1111. X    const char *match;
  1112. X    const char *p;
  1113. X
  1114. X    if((loc = db[match_who].location) != NOTHING) {
  1115. X    absolute = absolute_name();
  1116. X    if(!controls(match_who, absolute)) absolute = NOTHING;
  1117. X
  1118. X    DOLIST(exit, db[loc].exits) {
  1119. X        if(exit == absolute) {
  1120. X        exact_match = exit;
  1121. X        } else {
  1122. X        match = db[exit].name;
  1123. X        while(*match) {
  1124. X            /* check out this one */
  1125. X            for(p = match_name;
  1126. X            (*p
  1127. X             && DOWNCASE(*p) == DOWNCASE(*match)
  1128. X             && *match != EXIT_DELIMITER);
  1129. X            p++, match++);
  1130. X            /* did we get it? */
  1131. X            if(*p == '\0') {
  1132. X            /* make sure there's nothing afterwards */
  1133. X            while(isspace(*match)) match++;
  1134. X            if(*match == '\0' || *match == EXIT_DELIMITER) {
  1135. X                /* we got it */
  1136. X                exact_match = choose_thing(exact_match, exit);
  1137. X                goto next_exit;    /* got this match */
  1138. X            }
  1139. X            }
  1140. X            /* we didn't get it, find next match */
  1141. X            while(*match && *match++ != EXIT_DELIMITER);
  1142. X            while(isspace(*match)) match++;
  1143. X        }
  1144. X        }
  1145. X      next_exit:
  1146. X        ;
  1147. X    }
  1148. X    }
  1149. X}
  1150. X
  1151. Xvoid match_everything(void)
  1152. X{
  1153. X    match_exit();
  1154. X    match_neighbor();
  1155. X    match_possession();
  1156. X    match_me();
  1157. X    match_here();
  1158. X    if(Wizard(match_who)) {
  1159. X    match_absolute();
  1160. X    match_player();
  1161. X    }
  1162. X}
  1163. X
  1164. Xdbref match_result(void)
  1165. X{
  1166. X    if(exact_match != NOTHING) {
  1167. X    return exact_match;
  1168. X    } else {
  1169. X    switch(match_count) {
  1170. X      case 0:
  1171. X        return NOTHING;
  1172. X      case 1:
  1173. X        return last_match;
  1174. X      default:
  1175. X        return AMBIGUOUS;
  1176. X    }
  1177. X    }
  1178. X}
  1179. X       
  1180. X/* use this if you don't care about ambiguity */
  1181. Xdbref last_match_result(void)
  1182. X{
  1183. X    if(exact_match != NOTHING) {
  1184. X    return exact_match;
  1185. X    } else {
  1186. X    return last_match;
  1187. X    }
  1188. X}
  1189. X
  1190. Xdbref noisy_match_result(void)
  1191. X{
  1192. X    dbref match;
  1193. X
  1194. X    switch(match = match_result()) {
  1195. X      case NOTHING:
  1196. X    notify(match_who, NOMATCH_MESSAGE);
  1197. X    return NOTHING;
  1198. X      case AMBIGUOUS:
  1199. X    notify(match_who, AMBIGUOUS_MESSAGE);
  1200. X    return NOTHING;
  1201. X      default:
  1202. X    return match;
  1203. X    }
  1204. X}
  1205. X
  1206. END_OF_FILE
  1207. if test 5261 -ne `wc -c <'match.c'`; then
  1208.     echo shar: \"'match.c'\" unpacked with wrong size!
  1209. fi
  1210. # end of 'match.c'
  1211. fi
  1212. if test -f 'move.c' -a "${1}" != "-c" ; then 
  1213.   echo shar: Will not clobber existing file \"'move.c'\"
  1214. else
  1215. echo shar: Extracting \"'move.c'\" \(8534 characters\)
  1216. sed "s/^X//" >'move.c' <<'END_OF_FILE'
  1217. X#include "copyright.h"
  1218. X
  1219. X#include "db.h"
  1220. X#include "config.h"
  1221. X#include "interface.h"
  1222. X#include "match.h"
  1223. X#include "externs.h"
  1224. X
  1225. Xvoid moveto(dbref what, dbref where)
  1226. X{
  1227. X    dbref loc;
  1228. X
  1229. X    /* remove what from old loc */
  1230. X    if((loc = db[what].location) != NOTHING) {
  1231. X    db[loc].contents = remove_first(db[loc].contents, what);
  1232. X    }
  1233. X
  1234. X    /* test for special cases */
  1235. X    switch(where) {
  1236. X      case NOTHING:
  1237. X    db[what].location = NOTHING;
  1238. X    return;            /* NOTHING doesn't have contents */
  1239. X      case HOME:
  1240. X    where = db[what].exits;    /* home */
  1241. X    break;
  1242. X    }
  1243. X
  1244. X    /* now put what in where */
  1245. X    PUSH(what, db[where].contents);
  1246. X
  1247. X    db[what].location = where;
  1248. X}
  1249. X
  1250. Xstatic void send_contents(dbref loc, dbref dest)
  1251. X{
  1252. X    dbref first;
  1253. X    dbref rest;
  1254. X
  1255. X    first = db[loc].contents;
  1256. X    db[loc].contents = NOTHING;
  1257. X
  1258. X    /* blast locations of everything in list */
  1259. X    DOLIST(rest, first) {
  1260. X    db[rest].location = NOTHING;
  1261. X    }
  1262. X
  1263. X    while(first != NOTHING) {
  1264. X    rest = db[first].next;
  1265. X    if(Typeof(first) != TYPE_THING) {
  1266. X        moveto(first, loc);
  1267. X    } else {
  1268. X        moveto(first, (db[first].flags & STICKY) ? HOME : dest);
  1269. X    }
  1270. X    first = rest;
  1271. X    }
  1272. X
  1273. X    db[loc].contents = reverse(db[loc].contents);
  1274. X}
  1275. X
  1276. Xvoid maybe_dropto(dbref loc, dbref dropto)
  1277. X{
  1278. X    dbref thing;
  1279. X
  1280. X    if(loc == dropto) return;    /* bizarre special case */
  1281. X
  1282. X    /* check for players */
  1283. X    DOLIST(thing, db[loc].contents) {
  1284. X    if(Typeof(thing) == TYPE_PLAYER) return;
  1285. X    }
  1286. X    
  1287. X    /* no players, send everything to the dropto */
  1288. X    send_contents(loc, dropto);
  1289. X}
  1290. X
  1291. Xvoid enter_room(dbref player, dbref loc)
  1292. X{
  1293. X    dbref old;
  1294. X    dbref dropto;
  1295. X    char buf[BUFFER_LEN];
  1296. X
  1297. X    /* check for room == HOME */
  1298. X    if(loc == HOME) loc = db[player].exits; /* home */
  1299. X
  1300. X    /* get old location */
  1301. X    old = db[player].location;
  1302. X
  1303. X    /* check for self-loop */
  1304. X    /* self-loops don't do move or other player notification */
  1305. X    /* but you still get autolook and penny check */
  1306. X    if(loc != old) {
  1307. X
  1308. X    if(old != NOTHING) {
  1309. X        /* notify others unless DARK */
  1310. X        if(!Dark(old) && !Dark(player)) {
  1311. X        sprintf(buf, "%s has left.", db[player].name);
  1312. X        notify_except(db[old].contents, player, buf);
  1313. X        }
  1314. X    }
  1315. X
  1316. X    /* go there */
  1317. X    moveto(player, loc);
  1318. X
  1319. X    /* if old location has STICKY dropto, send stuff through it */
  1320. X    if(old != NOTHING
  1321. X       && (dropto = db[old].location) != NOTHING
  1322. X       && (db[old].flags & STICKY)) {
  1323. X        maybe_dropto(old, dropto);
  1324. X    }
  1325. X
  1326. X    /* tell other folks in new location if not DARK */
  1327. X    if(!Dark(loc) && !Dark(player)) {
  1328. X        sprintf(buf, "%s has arrived.", db[player].name);
  1329. X        notify_except(db[loc].contents, player, buf);
  1330. X    }
  1331. X    }
  1332. X
  1333. X    /* autolook */
  1334. X    look_room(player, loc);
  1335. X
  1336. X    /* check for pennies */
  1337. X    if(!controls(player, loc)
  1338. X       && db[player].pennies <= MAX_PENNIES
  1339. X       && random() % PENNY_RATE == 0) {
  1340. X    notify(player, "You found a penny!");
  1341. X    db[player].pennies++;
  1342. X    }
  1343. X}
  1344. X        
  1345. Xvoid send_home(dbref thing)
  1346. X{
  1347. X    switch(Typeof(thing)) {
  1348. X      case TYPE_PLAYER:
  1349. X    /* send his possessions home first! */
  1350. X    /* that way he sees them when he arrives */
  1351. X    send_contents(thing, HOME);
  1352. X    enter_room(thing, db[thing].exits); /* home */
  1353. X    break;
  1354. X      case TYPE_THING:
  1355. X    moveto(thing, db[thing].exits);    /* home */
  1356. X    break;
  1357. X      default:
  1358. X    /* no effect */
  1359. X    break;
  1360. X    }
  1361. X}
  1362. X    
  1363. Xint can_move(dbref player, const char *direction)
  1364. X{
  1365. X    if(!string_compare(direction, "home")) return 1;
  1366. X
  1367. X    /* otherwise match on exits */
  1368. X    init_match(player, direction, TYPE_EXIT);
  1369. X    match_exit();
  1370. X    return(last_match_result() != NOTHING);
  1371. X}
  1372. X
  1373. Xvoid do_move(dbref player, const char *direction)
  1374. X{
  1375. X    dbref exit;
  1376. X    dbref loc;
  1377. X    char buf[BUFFER_LEN];
  1378. X
  1379. X    if(!string_compare(direction, "home")) {
  1380. X    /* send him home */
  1381. X    /* but steal all his possessions */
  1382. X    if((loc = db[player].location) != NOTHING) {
  1383. X        /* tell everybody else */
  1384. X        sprintf(buf, "%s goes home.", db[player].name);
  1385. X        notify_except(db[loc].contents, player, buf);
  1386. X    }
  1387. X    /* give the player the messages */
  1388. X    notify(player, "There's no place like home...");
  1389. X    notify(player, "There's no place like home...");
  1390. X    notify(player, "There's no place like home...");
  1391. X    notify(player, "You wake up back home, without your possessions.");
  1392. X    send_home(player);
  1393. X    } else {
  1394. X    /* find the exit */
  1395. X    init_match_check_keys(player, direction, TYPE_EXIT);
  1396. X    match_exit();
  1397. X    switch(exit = match_result()) {
  1398. X      case NOTHING:
  1399. X        notify(player, "You can't go that way.");
  1400. X        break;
  1401. X      case AMBIGUOUS:
  1402. X        notify(player, "I don't know which way you mean!");
  1403. X        break;
  1404. X      default:
  1405. X        /* we got one */
  1406. X        /* check to see if we got through */
  1407. X        if(can_doit(player, exit, "You can't go that way.")) {
  1408. X        enter_room(player, db[exit].location);
  1409. X        }
  1410. X        break;
  1411. X    }
  1412. X    }
  1413. X}
  1414. X
  1415. Xvoid do_get(dbref player, const char *what)
  1416. X{
  1417. X    dbref loc;
  1418. X    dbref thing;
  1419. X
  1420. X    init_match_check_keys(player, what, TYPE_THING);
  1421. X    match_neighbor();
  1422. X    match_exit();
  1423. X    if(Wizard(player)) match_absolute(); /* the wizard has long fingers */
  1424. X
  1425. X    if((thing = noisy_match_result()) != NOTHING) {
  1426. X    if(db[thing].location == player) {
  1427. X        notify(player, "You already have that!");
  1428. X        return;
  1429. X    }
  1430. X    switch(Typeof(thing)) {
  1431. X      case TYPE_THING:
  1432. X        if(can_doit(player, thing, "You can't pick that up.")) {
  1433. X        moveto(thing, player);
  1434. X        notify(player, "Taken.");
  1435. X        }
  1436. X        break;
  1437. X      case TYPE_EXIT:
  1438. X        if(!controls(player, thing)) {
  1439. X        notify(player, "You can't pick that up.");
  1440. X        } else if(db[thing].location != NOTHING) {
  1441. X        notify(player, "You can't pick up a linked exit.");
  1442. X#ifdef RESTRICTED_BUILDING
  1443. X        } else if(!Builder(player)) {
  1444. X        notify(player, "Only authorized builders may pick up exits.");
  1445. X#endif /* RESTRICTED_BUILDING */
  1446. X        } else {
  1447. X        /* take it out of location */
  1448. X        if((loc = getloc(player)) == NOTHING) return;
  1449. X        if(!member(thing, db[loc].exits)) {
  1450. X            notify(player,
  1451. X               "You can't pick up an exit from another room.");
  1452. X            return;
  1453. X        }
  1454. X        db[loc].exits = remove_first(db[loc].exits, thing);
  1455. X        PUSH(thing, db[player].contents);
  1456. X        db[thing].location = player;
  1457. X        notify(player, "Exit taken.");
  1458. X        }
  1459. X        break;
  1460. X      default:
  1461. X        notify(player, "You can't take that!");
  1462. X        break;
  1463. X    }
  1464. X    }
  1465. X}
  1466. X
  1467. Xvoid do_drop(dbref player, const char *name)
  1468. X{
  1469. X    dbref loc;
  1470. X    dbref thing;
  1471. X    char buf[BUFFER_LEN];
  1472. X    int reward;
  1473. X
  1474. X    if((loc = getloc(player)) == NOTHING) return;    
  1475. X
  1476. X    init_match(player, name, TYPE_THING);
  1477. X    match_possession();
  1478. X
  1479. X    switch(thing = match_result()) {
  1480. X      case NOTHING:
  1481. X    notify(player, "You don't have that!");
  1482. X    break;
  1483. X      case AMBIGUOUS:
  1484. X    notify(player, "I don't know which you mean!");
  1485. X    break;
  1486. X      default:
  1487. X    if(db[thing].location != player &&
  1488. X       !(Typeof(thing) == TYPE_EXIT) && db[thing].location == NOTHING) {
  1489. X        /* Should not ever happen. */
  1490. X        notify(player, "You can't drop that.");
  1491. X    } else if(Typeof(thing) == TYPE_EXIT) {
  1492. X        /* special behavior for exits */
  1493. X        if(!controls(player, loc)) {
  1494. X        notify(player, "You can't put an exit down here.");
  1495. X        return;
  1496. X        }
  1497. X        /* else we can put it down */
  1498. X        moveto(thing, NOTHING); /* take it out of the pack */
  1499. X        PUSH(thing, db[loc].exits);
  1500. X        notify(player, "Exit dropped.");
  1501. X    } else if(db[loc].flags & TEMPLE) {
  1502. X        /* sacrifice time */
  1503. X        send_home(thing);
  1504. X        sprintf(buf,
  1505. X            "%s is consumed in a burst of flame!", db[thing].name);
  1506. X        notify(player, buf);
  1507. X#ifndef TINKER
  1508. X        sprintf(buf, "%s sacrifices %s.", db[player].name, db[thing].name);
  1509. X#else   TINKER
  1510. X        sprintf(buf, "%s donates %s.", db[player].name, db[thing].name);
  1511. X#endif  TINKER
  1512. X        notify_except(db[loc].contents, player, buf);
  1513. X
  1514. X        /* check for reward */
  1515. X        if(!controls(player, thing)) {
  1516. X        reward = db[thing].pennies;
  1517. X        if(reward < 1 || db[player].pennies > MAX_PENNIES) {
  1518. X            reward = 1;
  1519. X        } else if(reward > MAX_OBJECT_ENDOWMENT) {
  1520. X            reward = MAX_OBJECT_ENDOWMENT;
  1521. X        }
  1522. X
  1523. X        db[player].pennies += reward;
  1524. X        sprintf(buf,
  1525. X            "You have received %d %s for your donation.",
  1526. X            reward,
  1527. X            reward == 1 ? "penny" : "pennies");
  1528. X        notify(player, buf);
  1529. X        }
  1530. X    } else if(db[thing].flags & STICKY) {
  1531. X        send_home(thing);
  1532. X        notify(player, "Dropped.");
  1533. X    } else if(db[loc].location != NOTHING && !(db[loc].flags & STICKY)) {
  1534. X        /* location has immediate dropto */
  1535. X        moveto(thing, db[loc].location);
  1536. X        notify(player, "Dropped.");
  1537. X    } else if((db[thing].flags & DARK) && !can_link_to(player,Typeof(thing),loc)) {
  1538. X        notify(player, "You cannot drop that DARK object here.");
  1539. X    } else {
  1540. X        moveto(thing, loc);
  1541. X        notify(player, "Dropped.");
  1542. X        sprintf(buf, "%s dropped %s.", db[player].name, db[thing].name);
  1543. X        notify_except(db[loc].contents, player, buf);
  1544. X    }
  1545. X    break;
  1546. X    }
  1547. X}
  1548. END_OF_FILE
  1549. if test 8534 -ne `wc -c <'move.c'`; then
  1550.     echo shar: \"'move.c'\" unpacked with wrong size!
  1551. fi
  1552. # end of 'move.c'
  1553. fi
  1554. if test -f 'predicates.c' -a "${1}" != "-c" ; then 
  1555.   echo shar: Will not clobber existing file \"'predicates.c'\"
  1556. else
  1557. echo shar: Extracting \"'predicates.c'\" \(6557 characters\)
  1558. sed "s/^X//" >'predicates.c' <<'END_OF_FILE'
  1559. X#include "copyright.h"
  1560. X
  1561. X/* Predicates for testing various conditions */
  1562. X
  1563. X#include <ctype.h>
  1564. X
  1565. X#include "db.h"
  1566. X#include "interface.h"
  1567. X#include "config.h"
  1568. X#include "externs.h"
  1569. X
  1570. Xvoid pronoun_substitute(char *result, dbref player, const char *str);
  1571. X
  1572. Xint can_link_to(dbref who, object_flag_type what, dbref where)
  1573. X{
  1574. X    return(where >= 0 &&
  1575. X       where < db_top &&
  1576. X       Typeof(where) == TYPE_ROOM &&
  1577. X       (controls(who, where) ||
  1578. X        (what == NOTYPE &&
  1579. X         (Flag(where,LINK_OK|ABODE))) ||
  1580. X        (what == TYPE_ROOM &&
  1581. X         (Flag(where,ABODE))) ||
  1582. X        (what == TYPE_EXIT &&
  1583. X         (Flag(where,LINK_OK))) ||
  1584. X        ((what == TYPE_PLAYER || what == TYPE_THING) &&
  1585. X#ifdef ROBOT_MODE
  1586. X         (what != TYPE_PLAYER || !Robot(who) || !Robot(where)) &&
  1587. X#endif ROBOT_MODE
  1588. X         Flag(where,ABODE))));
  1589. X    }
  1590. X
  1591. X/*
  1592. X * Check whether a player can perform an action...robotic players are
  1593. X * now implicitly barred from performing actions on things with the
  1594. X * robot flag set.    5/18/90 - Fuzzy
  1595. X */
  1596. X
  1597. Xint could_doit(dbref player, dbref thing)
  1598. X{
  1599. X    if(Typeof(thing) != TYPE_ROOM && db[thing].location == NOTHING) return 0;
  1600. X
  1601. X#ifdef ROBOT_MODE
  1602. X    if(Typeof(thing) != TYPE_PLAYER && Robot(player) && Robot(thing)) return 0;
  1603. X    if(Typeof(thing) == TYPE_EXIT && Robot(player) &&
  1604. X        db[thing].location >= 0 && Robot(db[thing].location)) return 0;
  1605. X#endif ROBOT_MODE
  1606. X
  1607. X    return(eval_boolexp (player, db[thing].key));
  1608. X}
  1609. X
  1610. Xint can_doit(dbref player, dbref thing, const char *default_fail_msg)
  1611. X{
  1612. X    dbref loc;
  1613. X    char buf[BUFFER_LEN];
  1614. X
  1615. X    if((loc = getloc(player)) == NOTHING) return 0;
  1616. X
  1617. X    if(!could_doit(player, thing)) {
  1618. X    /* can't do it */
  1619. X    if(db[thing].fail_message) {
  1620. X        notify(player, db[thing].fail_message);
  1621. X    } else if(default_fail_msg) {
  1622. X        notify(player, default_fail_msg);
  1623. X    }
  1624. X    
  1625. X    if(db[thing].ofail && !Dark(player)) {
  1626. X#ifdef GENDER
  1627. X        pronoun_substitute(buf, player, db[thing].ofail);
  1628. X#else        
  1629. X        sprintf(buf, "%s %s", db[player].name, db[thing].ofail);
  1630. X#endif /* GENDER */
  1631. X        notify_except(db[loc].contents, player, buf);
  1632. X    }
  1633. X
  1634. X    return 0;
  1635. X    } else {
  1636. X    /* can do it */
  1637. X    if(db[thing].succ_message) {
  1638. X        notify(player, db[thing].succ_message);
  1639. X    }
  1640. X
  1641. X    if(db[thing].osuccess && !Dark(player)) {
  1642. X#ifdef GENDER
  1643. X        pronoun_substitute(buf, player, db[thing].osuccess);
  1644. X#else
  1645. X        sprintf(buf, "%s %s", db[player].name, db[thing].osuccess);
  1646. X#endif /* GENDER */
  1647. X        notify_except(db[loc].contents, player, buf);
  1648. X    }
  1649. X
  1650. X    return 1;
  1651. X    }
  1652. X}
  1653. X
  1654. Xint can_see(dbref player, dbref thing, int can_see_loc)
  1655. X{
  1656. X    if(player == thing || Typeof(thing) == TYPE_EXIT) {
  1657. X    return 0;
  1658. X    } else if(can_see_loc) {
  1659. X    return(!Dark(thing) || controls(player, thing));
  1660. X    } else {
  1661. X    /* can't see loc */
  1662. X    return(controls(player, thing));
  1663. X    }
  1664. X}
  1665. X
  1666. Xint controls(dbref who, dbref what)
  1667. X{
  1668. X    /* Wizard controls everything */
  1669. X    /* owners control their stuff */
  1670. X    return(what >= 0
  1671. X       && what < db_top
  1672. X       && (Wizard(who)
  1673. X           || who == db[what].owner));
  1674. X}
  1675. X
  1676. Xint can_link(dbref who, dbref what)
  1677. X{
  1678. X    return((Typeof(what) == TYPE_EXIT && db[what].location == NOTHING)
  1679. X       || controls(who, what));
  1680. X}
  1681. X
  1682. Xint payfor(dbref who, int cost)
  1683. X{
  1684. X    if(Wizard(who)) {
  1685. X    return 1;
  1686. X    } else if(db[who].pennies >= cost) {
  1687. X    db[who].pennies -= cost;
  1688. X    return 1;
  1689. X    } else {
  1690. X    return 0;
  1691. X    }
  1692. X}
  1693. X
  1694. Xint word_start (const char *str, const char let)
  1695. X{
  1696. X    int chk;
  1697. X
  1698. X    for (chk = 1; *str; str++) {
  1699. X    if (chk && *str == let) return 1;
  1700. X    chk = *str == ' ';
  1701. X    }
  1702. X    return 0;
  1703. X}
  1704. X
  1705. X
  1706. Xint ok_name(const char *name)
  1707. X{
  1708. X    return (name
  1709. X        && *name
  1710. X        && *name != LOOKUP_TOKEN
  1711. X        && *name != NUMBER_TOKEN
  1712. X        && !index(name, ARG_DELIMITER)
  1713. X        && !index(name, AND_TOKEN)
  1714. X        && !index(name, OR_TOKEN)
  1715. X        && !word_start(name, NOT_TOKEN)
  1716. X#ifdef NOFAKES
  1717. X        && string_compare(name, "A")
  1718. X        && string_compare(name, "An")
  1719. X        && string_compare(name, "The")
  1720. X        && string_compare(name, "You")
  1721. X        && string_compare(name, "Your")
  1722. X        && string_compare(name, "Going")
  1723. X            && string_compare(name, "Huh?")
  1724. X#endif NOFAKES
  1725. X        && string_compare(name, "me")        
  1726. X        && string_compare(name, "home")
  1727. X        && string_compare(name, "here"));
  1728. X}
  1729. X
  1730. Xint ok_player_name(const char *name)
  1731. X{
  1732. X    const char *scan;
  1733. X
  1734. X    if(!ok_name(name) || strlen(name) > PLAYER_NAME_LIMIT) return 0;
  1735. X
  1736. X    for(scan = name; *scan; scan++) {
  1737. X    if(!(isprint(*scan) && !isspace(*scan))) { /* was isgraph(*scan) */
  1738. X        return 0;
  1739. X    }
  1740. X    }
  1741. X
  1742. X    /* lookup name to avoid conflicts */
  1743. X    return (lookup_player(name) == NOTHING);
  1744. X}
  1745. X
  1746. Xint ok_password(const char *password)
  1747. X{
  1748. X    const char *scan;
  1749. X
  1750. X    if(*password == '\0') return 0;
  1751. X
  1752. X    for(scan = password; *scan; scan++) {
  1753. X    if(!(isprint(*scan) && !isspace(*scan))) {
  1754. X        return 0;
  1755. X    }
  1756. X    }
  1757. X
  1758. X    return 1;
  1759. X}
  1760. X
  1761. X#ifdef GENDER
  1762. X/*
  1763. X * pronoun_substitute()
  1764. X *
  1765. X * %-type substitutions for pronouns
  1766. X *
  1767. X * %s/%S for subjective pronouns (he/she/it, He/She/It)
  1768. X * %o/%O for objective pronouns (him/her/it, Him/Her/It)
  1769. X * %p/%P for possessive pronouns (his/her/its, His/Her/Its)
  1770. X * %n    for the player's name.
  1771. X */
  1772. Xvoid pronoun_substitute(char *result, dbref player, const char *str)
  1773. X{
  1774. X    char c;
  1775. X
  1776. X    const static char *subjective[4] = { "", "it", "she", "he" };
  1777. X    const static char *possessive[4] = { "", "its", "her", "his" };
  1778. X    const static char *objective[4] = { "", "it", "her", "him" };
  1779. X
  1780. X#ifdef COMPRESS
  1781. X    str = uncompress(str);
  1782. X#endif /* COMPRESS */
  1783. X    strcpy(result, db[player].name);
  1784. X    result += strlen(result);
  1785. X    *result++ = ' ';
  1786. X    while (*str) {
  1787. X    if(*str == '%') {
  1788. X        *result = '\0';
  1789. X        c = *(++str);
  1790. X        if (Genderof(player) == GENDER_UNASSIGNED) {
  1791. X        switch(c) {
  1792. X          case 'n':
  1793. X          case 'N':
  1794. X          case 'o':
  1795. X          case 'O':
  1796. X          case 's':
  1797. X          case 'S':
  1798. X            strcat(result, db[player].name);
  1799. X            break;
  1800. X          case 'p':
  1801. X          case 'P':
  1802. X            strcat(result, db[player].name);
  1803. X            strcat(result, "'s");
  1804. X            break;
  1805. X          default:
  1806. X            result[0] = *str;
  1807. X            result[1] = 0;
  1808. X            break;
  1809. X        }
  1810. X        str++;
  1811. X        result += strlen(result);
  1812. X        } else {
  1813. X        switch (c) {
  1814. X          case 's':
  1815. X          case 'S':
  1816. X            strcat(result, subjective[Genderof(player)]);
  1817. X            break;
  1818. X          case 'p':
  1819. X          case 'P':
  1820. X            strcat(result, possessive[Genderof(player)]);
  1821. X            break;
  1822. X          case 'o':
  1823. X          case 'O':
  1824. X            strcat(result, objective[Genderof(player)]);
  1825. X            break;
  1826. X          case 'n':
  1827. X          case 'N':
  1828. X            strcat(result, db[player].name);
  1829. X            break;
  1830. X          default:
  1831. X            *result = *str;
  1832. X            result[1] = '\0';
  1833. X            break;
  1834. X        } 
  1835. X        if(isupper(c) && islower(*result)) {
  1836. X            *result = toupper(*result);
  1837. X        }
  1838. X        
  1839. X        result += strlen(result);
  1840. X        str++;
  1841. X        }
  1842. X    } else {
  1843. X        *result++ = *str++;
  1844. X    }
  1845. X    }
  1846. X    *result = '\0';
  1847. X} 
  1848. X
  1849. X#endif /* GENDER */
  1850. END_OF_FILE
  1851. if test 6557 -ne `wc -c <'predicates.c'`; then
  1852.     echo shar: \"'predicates.c'\" unpacked with wrong size!
  1853. fi
  1854. # end of 'predicates.c'
  1855. fi
  1856. if test -f 'speech.c' -a "${1}" != "-c" ; then 
  1857.   echo shar: Will not clobber existing file \"'speech.c'\"
  1858. else
  1859. echo shar: Extracting \"'speech.c'\" \(5423 characters\)
  1860. sed "s/^X//" >'speech.c' <<'END_OF_FILE'
  1861. X#include "copyright.h"
  1862. X
  1863. X/* Commands which involve speaking */
  1864. X
  1865. X#include "db.h"
  1866. X#include "interface.h"
  1867. X#include "match.h"
  1868. X#include "config.h"
  1869. X#include "externs.h"
  1870. X
  1871. X/* this function is a kludge for regenerating messages split by '=' */
  1872. Xconst char *reconstruct_message(const char *arg1, const char *arg2)
  1873. X{
  1874. X    static char buf[BUFFER_LEN];
  1875. X
  1876. X    if(arg2 && *arg2) {
  1877. X    strcpy(buf, arg1);
  1878. X    strcat(buf, " = ");
  1879. X    strcat(buf, arg2);
  1880. X    return buf;
  1881. X    } else {
  1882. X    return arg1;
  1883. X    }
  1884. X}
  1885. X
  1886. Xvoid do_say(dbref player, const char *arg1, const char *arg2)
  1887. X{
  1888. X    dbref loc;
  1889. X    const char *message;
  1890. X    char buf[BUFFER_LEN];
  1891. X
  1892. X    if((loc = getloc(player)) == NOTHING) return;
  1893. X
  1894. X    message = reconstruct_message(arg1, arg2);
  1895. X
  1896. X    /* notify everybody */
  1897. X    sprintf(buf, "You say \"%s\"", message);
  1898. X    notify(player, buf);
  1899. X    sprintf(buf, "%s says \"%s\"", db[player].name, message);
  1900. X    notify_except(db[loc].contents, player, buf);
  1901. X}
  1902. X
  1903. Xvoid do_whisper(dbref player, const char *arg1, const char *arg2)
  1904. X{
  1905. X#ifndef QUIET_WHISPER
  1906. X    dbref loc;
  1907. X#endif QUIET_WHISPER
  1908. X    dbref who;
  1909. X    char buf[BUFFER_LEN];
  1910. X    char *det;
  1911. X    int result;
  1912. X
  1913. X    init_match(player, arg1, TYPE_PLAYER);
  1914. X    match_neighbor();
  1915. X    match_me();
  1916. X    if(Wizard(player)) {
  1917. X    match_absolute();
  1918. X    match_player();
  1919. X    }
  1920. X    switch(who = match_result()) {
  1921. X      case NOTHING:
  1922. X    notify(player, "Whisper to whom?");
  1923. X    break;
  1924. X      case AMBIGUOUS:
  1925. X    notify(player, "I don't know who you mean!");
  1926. X    break;
  1927. X      default:
  1928. X        if (Typeof(who) == TYPE_PLAYER) {
  1929. X        sprintf(buf, "%s whispers \"%s\"", db[player].name, arg2);
  1930. X        if (notify(who, buf)) {
  1931. X        sprintf(buf, "You whisper \"%s\" to %s.", arg2, db[who].name);
  1932. X            notify(player, buf);
  1933. X#ifndef QUIET_WHISPER
  1934. X        sprintf(buf, "%s whispers something to %s.",
  1935. X            db[player].name, db[who].name);
  1936. X        if((loc = getloc(player)) != NOTHING) {
  1937. X            notify_except2(db[loc].contents, player, who, buf);
  1938. X        }
  1939. X#endif /* QUIET_WHISPER */
  1940. X        }
  1941. X        else
  1942. X        notify(player, "That person is not connected.");
  1943. X    } else {
  1944. X        if (string_prefix (db[who].name, "a ") ||
  1945. X            string_prefix (db[who].name, "an ") ||
  1946. X            string_prefix (db[who].name, "the ") ||
  1947. X            string_prefix (db[who].name, "some ")) {
  1948. X        det = "";
  1949. X        } else if (lookup_player (db[who].name) != NOTHING) {
  1950. X               det = "the thing called ";
  1951. X            } else {
  1952. X        det = "the ";
  1953. X        }
  1954. X        sprintf(buf, "You feel silly about whispering to %s%s.",
  1955. X            det, db[who].name);
  1956. X        notify(player, buf);
  1957. X    }
  1958. X    break;
  1959. X    }
  1960. X}
  1961. X
  1962. Xvoid do_pose(dbref player, const char *arg1, const char *arg2)
  1963. X{
  1964. X    dbref loc;
  1965. X    const char *message;
  1966. X    char buf[BUFFER_LEN];
  1967. X
  1968. X    if((loc = getloc(player)) == NOTHING) return;
  1969. X
  1970. X    message = reconstruct_message(arg1, arg2);
  1971. X
  1972. X    /* notify everybody */
  1973. X    sprintf(buf, "%s %s", db[player].name, message);
  1974. X    notify_except(db[loc].contents, NOTHING, buf);
  1975. X}
  1976. X
  1977. Xvoid do_wall(dbref player, const char *arg1, const char *arg2)
  1978. X{
  1979. X    dbref i;
  1980. X    const char *message;
  1981. X    char buf[512];
  1982. X
  1983. X    message = reconstruct_message(arg1, arg2);
  1984. X    if(Wizard(player)) {
  1985. X    writelog("WALL from %s(%d): %s\n",
  1986. X        db[player].name, player, message);
  1987. X    sprintf(buf, "%s shouts \"%s\"", db[player].name, message);
  1988. X    for(i = 0; i < db_top; i++) {
  1989. X        if(Typeof(i) == TYPE_PLAYER) {
  1990. X        notify(i, buf);
  1991. X        }
  1992. X    }
  1993. X    } else {
  1994. X    notify(player, "But what do you want to do with the wall?");
  1995. X    }
  1996. X}
  1997. X
  1998. Xvoid do_gripe(dbref player, const char *arg1, const char *arg2)
  1999. X{
  2000. X    dbref loc;
  2001. X    const char *message;
  2002. X
  2003. X    loc = db[player].location;
  2004. X    message = reconstruct_message(arg1, arg2);
  2005. X    writelog("GRIPE from %s(%d) in %s(%d): %s\n",
  2006. X        db[player].name, player,
  2007. X        db[loc].name, loc,
  2008. X        message);
  2009. X    fflush(stderr);
  2010. X
  2011. X#ifdef GOD_PRIV
  2012. X    /* try telling GOD about it */
  2013. X    if (!Flag(GOD,HAVEN)) {
  2014. X    char buf[BUFFER_LEN];
  2015. X    sprintf(buf, "%s gripes: \"%s\"",
  2016. X        unparse_object(GOD, player), message);
  2017. X    notify(GOD, buf);
  2018. X    }
  2019. X#endif GOD_PRIV    
  2020. X
  2021. X    notify(player, "Your complaint has been duly noted.");
  2022. X}
  2023. X
  2024. X/* doesn't really belong here, but I couldn't figure out where else */
  2025. Xvoid do_page(dbref player, const char *arg1, const char *arg2)
  2026. X{
  2027. X    char buf[BUFFER_LEN];
  2028. X    dbref target;
  2029. X    int result;
  2030. X
  2031. X    if(!payfor(player, PAGE_COST)) {
  2032. X    notify(player, "You don't have enough pennies.");
  2033. X    } else if((target = lookup_player(arg1)) == NOTHING) {
  2034. X    notify(player, "I don't recognize that name.");
  2035. X    } else if (db[target].flags & HAVEN) {
  2036. X    notify(player, "That player is not accepting pages.");
  2037. X    } else if (arg2 && *arg2) {
  2038. X    sprintf(buf, "%s pages: %s", db[player].name, arg2);
  2039. X    result = notify(target, buf);
  2040. X    if (result) 
  2041. X        notify(player, "Your message has been sent.");
  2042. X    else
  2043. X        notify(player, "That person is not connected.");
  2044. X    } else {
  2045. X    sprintf(buf, "You sense that %s is looking for you in %s.",
  2046. X        db[player].name, db[db[player].location].name);
  2047. X    result = notify(target, buf);
  2048. X    if (result)
  2049. X        notify(player, "Your message has been sent.");
  2050. X    else
  2051. X        notify(player, "That person is not connected.");
  2052. X    }
  2053. X}
  2054. X
  2055. Xvoid notify_except(dbref first, dbref exception, const char *msg)
  2056. X{
  2057. X    DOLIST (first, first) {
  2058. X    if ((db[first].flags & TYPE_MASK) == TYPE_PLAYER
  2059. X        && first != exception) {
  2060. X        notify (first, msg);
  2061. X    }
  2062. X    }
  2063. X}
  2064. X
  2065. Xvoid notify_except2(dbref first, dbref exc1, dbref exc2, const char *msg)
  2066. X{
  2067. X    DOLIST (first, first) {
  2068. X    if ((db[first].flags & TYPE_MASK) == TYPE_PLAYER
  2069. X        && first != exc1
  2070. X        && first != exc2) {
  2071. X        notify (first, msg);
  2072. X    }
  2073. X    }
  2074. X}
  2075. END_OF_FILE
  2076. if test 5423 -ne `wc -c <'speech.c'`; then
  2077.     echo shar: \"'speech.c'\" unpacked with wrong size!
  2078. fi
  2079. # end of 'speech.c'
  2080. fi
  2081. echo shar: End of archive 9 \(of 10\).
  2082. cp /dev/null ark9isdone
  2083. MISSING=""
  2084. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  2085.     if test ! -f ark${I}isdone ; then
  2086.     MISSING="${MISSING} ${I}"
  2087.     fi
  2088. done
  2089. if test "${MISSING}" = "" ; then
  2090.     echo You have unpacked all 10 archives.
  2091.     echo ">>> now type 'sh joinspl.sh'"
  2092.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2093. else
  2094.     echo You still need to unpack the following archives:
  2095.     echo "        " ${MISSING}
  2096. fi
  2097. ##  End of shell archive.
  2098. exit 0
  2099.